package com.yunhe.abnormal.service.data;

import com.yunhe.abnormal.domain.base.AlarmLevel;
import com.yunhe.abnormal.domain.data.AlarmEvent;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.abnormal.model.AlarmEventSearchDTO;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.model.authority.StationDTO;
import com.yunhe.common.model.base.AbnormalStatusDTO;
import com.yunhe.common.model.base.AlarmLevelDTO;
import com.yunhe.common.model.data.AlarmEventDTO;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 告警事件Service
 * @desc 告警事件服务类定义
 * @author duanxiaoyong
 */
public interface AlarmEventService {

    /**
     * 新增事件对象
     * @param event 事件对象
     */
    AlarmEventDTO createEvent(AlarmEvent event)
            throws Exception;

    /**
     * 批量新增事件对象
     * @param eventList 事件对象列表
     */
    Iterable<AlarmEventDTO> createEvent(List<AlarmEvent> eventList)
            throws Exception;

    AlarmEventDTO createForHistory(AlarmEvent alarmEvent);

    /**
     * 根据事件ID删除事件对象
     * @param id 事件ID
     */
    void deleteEventById(Long id);

    void deleteEventById(List<Long> ids);

    void deleteEventByStationId(Long stationId);

    void deleteEventByStationId(Long stationId, List<Date> dtime) throws ArgumentErrorException;

    /**
     * 更新事件（更新全部字段）
     * @param event 事件对象
     */
    AlarmEventDTO updateEvent(AlarmEvent event)
            throws ArgumentErrorException, ObjectNotFoundException, UniqueConstraintsException;


    /**
     * 更新事件（指定字段）
     * @param id 事件ID
     * @param firmId 单位ID
     * @param firmTitle 单位名称
     * @param stationId 电站ID
     * @param stationTitle 电站名称
     * @param devId 设备ID
     * @param devTitle 设备标题
     * @param alarmStatusId 异常名称ID
     * @param alarmStatusTitle 异常名称名称
     * @param alarmTypeId 告警类型ID
     * @param alarmTypeTitle 告警类型名称
     * @param abnormalStatusId 告警状态ID
     * @param abnormalStatusTitle 告警状态名称
     * @param userIdProcess 处理人ID
     * @param userTitleProcess 处理人姓名
     * @param continueTime 持续时间
     * @param startTime 开始时间
     * @param latestProcessTime 最新处理时间
     * @return
     * @throws ArgumentErrorException
     * @throws ObjectNotFoundException
     * @throws UniqueConstraintsException
     */
    AlarmEventDTO updateEvent(Long id,
                              Optional<Long> firmId,
                              Optional<String> firmTitle,
                              Optional<Long> stationId,
                              Optional<String> stationTitle,
                              Optional<Long> devId,
                              Optional<String> devTitle,
                              Optional<Long> alarmStatusId,
                              Optional<String> alarmStatusTitle,
                              Optional<Long> alarmTypeId,
                              Optional<String> alarmTypeTitle,
                              Optional<Long> abnormalStatusId,
                              Optional<String> abnormalStatusTitle,
                              Optional<Long> userIdProcess,
                              Optional<String> userTitleProcess,
                              Optional<Long> continueTime,
                              Optional<String> startTime,
                              Optional<String> latestProcessTime)
            throws ArgumentErrorException, ObjectNotFoundException, UniqueConstraintsException;

    /**
     * 根据事件ID获得事件
     * @param id 事件ID
     */
    AlarmEventDTO findById(Long id);

    /**
     *
     * @param devId
     */
    Iterable<AlarmEventDTO> findEvents(Long devId,
                                       Long alarmTypeId,
                                       Long alarmStatusId);

    AlarmEventDTO findEvents(Long devId, Long alarmTypeId);

    Iterable<AlarmEventDTO> findAllWarning();

    Iterable<AlarmEvent> findAllWarningByFirmAndUser(Optional<Long> firmId, Optional<Long> userId, Optional<List<Long>> stationList, Optional<Boolean> isAll, PageParam pageParam);

    Iterable<AlarmEventDTO> findAllWarningByFirmId(Long firmId);

    /**
     * 根据条件查询事件
     * @param dtime 时间范围
     * @param queryStr 查询参数
     * @param pageParam 分页条件
     */
    Iterable<AlarmEvent> findByCondition(Long firmId,
                                         List<Long> stationIds,
                                         Long devId,
                                         Long alarmStatusId,
                                         Long alarmTypeId,
                                         List<Long> abnormalStatusIds,
                                         List<Long> alarmLevelIds,
                                         String dtime,
                                         String queryStr,
                                         PageParam pageParam);

    /**
     * 查询最后一条事件记录
     */
    AlarmEventDTO findLastEvent();

    /**
     * 根据单位和告警状态查找告警事件
     * @param firmId 单位代码
     * @param alarmStatusId 告警状态
     */
    Iterable<AlarmEventDTO> search(Long firmId, Long alarmStatusId);

    /**
     * 按天和告警状态查找告警事件数量
     * @param stationId 电站ID
     * @param devId 设备ID
     * @param abnormalStatusId 异常状态ID
     * @param alarmStatusId 告警状态ID
     * @param dtime 时间段
     * @return
     */
    Map<String, Integer> searchDay(Optional<List<Long>> stationId,
                                   Optional<Long> devId,
                                   Optional<Long> abnormalStatusId,
                                   Optional<Long> alarmStatusId,
                                   Optional<Long> alarmLevelId,
                                   List<String> dtime);

    /**
     * 按月和告警状态查找告警事件数量
     * @param stationId 单位代码
     * @param abnormalStatusId 异常状态Id
     * @param dtime 时间范围
     */
    Map<String, Integer> searchMonth(Optional<List<Long>> stationId,
                                     Optional<Long> devId,
                                     Optional<Long> abnormalStatusId,
                                     Optional<Long> alarmLevelId,
                                     List<String> dtime);

    /**
     * 按月和告警状态查找告警事件数量
     * @param stationId 单位代码
     * @param abnormalStatusId 异常状态Id
     * @param dtime 时间范围
     */
    Map<String, Integer> searchYear(Optional<List<Long>> stationId,
                                    Optional<Long> devId,
                                    Optional<Long> abnormalStatusId,
                                    Optional<Long> alarmLevelId,
                                    List<String> dtime);


    Map<String, Integer> searchTopDevice(Optional<List<Long>> stationIds,
                                         List<String> dtime,
                                         List<Long> alarmLevelIds);

    Map<String, Integer> searchTopAlarmStatus(Optional<List<Long>> stationIds,
                                              List<String> dtime,
                                              List<Long> alarmLevelIds);


    /**
     * 根据单位查找告警事件数量
     * @param stationId 单位代码
     * @param dtime 时间范围
     */
    Map<String, Integer> searchAmount(Long stationId, Optional<Long> alarmLevelId, List<Date> dtime);

    /**
     * 根据起止时间查找电站的告警数量
     * @param stationId 电站ID
     * @param dtime 时间范围
     */
    Map<Long, Integer> amountGroupByEnergyUnit(Long stationId, List<Date> dtime);

    /**
     * 获取新增或者状态发生改变的事件
     * @param firmId 单位
     */
    List<AlarmEventDTO> searchChange(Long firmId);

    /**
     * 根据电站ID获得全部正在告警事件
     * @param stationId
     * @return
     */
    Iterable<AlarmEvent> findWarningByStationId(Long stationId, PageParam pageParam);

    /**
     * 查找所有调式中产生的告警
     * @return
     */
//    Iterable<AlarmEventDTO> findDebuggingEvent();


    /**
     * 根据电站ID和告警等级获得当日正在告警的事件
     * @param stationId
     * @param alarmLevelId
     * @return
     */
    List<AlarmEventSearchDTO> findWarningDayByStationAndAlarmLevel(Long stationId, Long alarmLevelId) throws ArgumentErrorException;

    /**
     * 根据电站ID获得当日遥信事件数量
     *
     * @param stationId
     * @return
     */
    List<AlarmEventSearchDTO> findEventDayByStationIdAndTypeName(Long stationId, Long alarmLevelId) throws ArgumentErrorException;

    Map<String, Integer> realTimeWarningCountByStationIds(List<Long> stationIds);

    /**
     * 根据电站ID获取告警事件的最高等级
     * @param stationId
     * @return
     */
    AlarmLevel getHighestLevelByStationId(Long stationId);

    /**
     * 根据设备ID获取告警事件的最高等级
     * @param deviceId
     * @return
     */
    AlarmLevel getHighestLevelByDeviceIds(Long deviceId);

    /**
     * 清除对应设备和告警规则的事件
     * @param deviceStatusMap
     * @throws ArgumentErrorException
     * @throws ObjectNotFoundException
     * @throws UniqueConstraintsException
     */
    void clearEventNotEliminated(Map<Long, List<Long>> deviceStatusMap) throws ArgumentErrorException, ObjectNotFoundException,
            UniqueConstraintsException;

    /**
     * 获得当前告警中的异常Map
     * InstanceId: eventId
     */
    Map<String, AlarmEvent> getCurrentEventMap();

    /**
     * 根据告警规则ID和开始时间获得历史最接近开始时间的第一条记录
     * @param ruleId 异常示例ID
     * @param startRtime 开始时间
     */
    AlarmEvent getLastHistoryEventByStartTime(Long ruleId, Long startRtime, Long endRtime);

    /**
     * 根据告警规则ID和时间范围获得范围内的第一条记录
     * @param ruleId 异常示例ID
     * @param startRtime 开始时间
     * @param endRtime 结束时间
     */
    AlarmEvent getFirstEventByRuleAndTimeRange(Long ruleId, Long startRtime, Long endRtime);

    /**
     * 历史告警更新
     * @param alarmEvent
     */
    AlarmEventDTO updateForHistory(AlarmEvent alarmEvent);

//    void createEventFromDpu(List<AlarmEventDpuDTO> alarmEventDpuDTOList);
//
//    AlarmNotifyDTO getAlarmNotify(Map<Long, Double> pnValueMap,
//                                  AlarmCalculation ruleInstance,
//                                  Long rtime, Double result);
//
//    AlarmEvent createEvent(AlarmCalculation ruleInstance,
//                           StationDTO station,
//                           AbnormalStatusDTO status,
//                           Long rtime,
//                           boolean needSave);
}